package mainserver;
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MainServer extends Thread{
    
    private Socket mainServerConnection;
    private String mainsServerTimeStamp;
    private int ID;
    private static List<File> fileList = null;    
    
    public MainServer(Socket mainServerSocket, int ID){
        this.mainServerConnection = mainServerSocket;
        this.ID = ID;
    }
   
    @Override
    public void run(){
        System.out.println("\nNew Thread created.");
        BufferedInputStream bufferedInputStream = null;
        try {
            /* Receiving Message. */
            bufferedInputStream = new BufferedInputStream(mainServerConnection.getInputStream());
            InputStreamReader inputStreamReader = new InputStreamReader(bufferedInputStream);
            int readCharactere;
            StringBuffer receivedMessage = new StringBuffer();
            while((readCharactere = inputStreamReader.read()) != (char)13){
                receivedMessage.append((char) readCharactere);
            } 
            
            /* Check Message for Instructions. */ 
            String message = receivedMessage.toString();
            String messageParts[] = message.split(" ");
            System.out.println("\nMessage: " + message);
            String sentMessage = "";
            
            switch(messageParts[0]){
                /* Recevie a File List and UpDate FileTable. */
                case "upList":
                    File file;
                    String[] fileName = messageParts[1].split("/");
                    boolean iHaveIt = false;
                    if(fileList.isEmpty()){
                            file = new File(fileName[0], mainServerConnection.getInetAddress().getHostName());
                                fileList.add(file);
                        }
                    for(int i = 0; i < fileName.length; i++){
                        //iHaveIt = false;
                        for(int j = 0; j < fileList.size(); j++){
                            iHaveIt = false;
                            //System.out.println(fileName[i] + " = " + fileList.get(j).getFileName());
                            if(fileName[i].equals(fileList.get(j).getFileName())){
                                iHaveIt = true;
                                if(!fileList.get(j).whoHasMe.contains(mainServerConnection.getInetAddress().getHostName())){
                                    fileList.get(j).whoHasMe.add(mainServerConnection.getInetAddress().getHostName());
                                    iHaveIt = true;
                                }
                                break;
                            } 
                        }
                        if(iHaveIt == false){
                                file = new File(fileName[i], mainServerConnection.getInetAddress().getHostName());
                                fileList.add(file);
                            }
                    }
                    sentMessage = "ACK" + (char)13;
                    break;
                
                /* Receive a File Solicitation. */
                case "getFile":
                    //String[] fileName2 = messageParts[1].split("/");
                    for(int i = 0; i < fileList.size(); i++){
                        System.out.println("Looking For File.");
                        if(fileList.get(i).fileName.equals(messageParts[1])){
                            System.out.println("Got the File.");
                            sentMessage = fileList.get(i).whoHasMe.get(0) + (char)13;
                            System.out.println("Here is the File: " + sentMessage);
                            break;
                        }
                        
                    }
                    break;
                /* Receive a file removed Notification. */
                case "rmFile":
                    for(int i = 0; i < fileList.size(); i++){
                        if(fileList.get(i).getFileName().equals(messageParts[1])){
                            fileList.get(i).whoHasMe.remove(mainServerConnection.getInetAddress().getHostName());
                            if(fileList.get(i).whoHasMe.isEmpty()){
                                fileList.remove(i);
                            }
                        }
                    }
                    sentMessage = "ACK" + (char)13;
                    break;
                /* Receive a Open File Solicitation. */
                case "openFile":
                    for(int i = 0; i < fileList.size(); i++){
                        if(fileList.get(i).getFileName().equals(messageParts[1])){
                            if(!fileList.get(i).beingWriten){
                                sentMessage = "ACK" + (char)13;
                                fileList.get(i).beingWriten = true;
                                //System.out.println(fileList.get(i).beingWriten);
                            }
                            else{
                                sentMessage = "DENIED" + (char)13;
                            }
                            break;
                        }
                    }
                    break;
                 /* Receive a close File Notification. */
                case "closeFile":
                    for(int i = 0; i < fileList.size(); i++){
                        if(fileList.get(i).getFileName().equals(messageParts[1])){
                            fileList.get(i).beingWriten = false;
                            sentMessage = "ACK" + (char)13;
                            break;
                        }
                    }
                    break;
                
                /* Receive a File List Solicitation. */
                case "getList":
                    break;
                
                /* Receive all Files List Solicitation. */
                case "getListAll":
                    int i;
                    for(i = 0; i < fileList.size()-1; i++){
                        sentMessage = sentMessage + fileList.get(i).getFileName() + "/";
                    }
                    sentMessage = sentMessage + fileList.get(i).getFileName() + (char)13;
                    break;
                default:
                    break;
            }
            /* Print FileList. */
            for(int i = 0; i < fileList.size(); i++){
                System.out.println(fileList.get(i).getFileName());
                for(int j = 0; j < fileList.get(i).whoHasMe.size(); j++){
                    System.out.println(fileList.get(i).whoHasMe.get(j) + "\n");
                }
            }
            /* Send Message. */
            //sentMessage = "ACK" + (char)13;
            System.out.println(sentMessage);
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(mainServerConnection.getOutputStream());
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(bufferedOutputStream, "US-ASCII");
            outputStreamWriter.write(sentMessage);
            outputStreamWriter.flush();
            
            /* Close Connection */
            mainServerConnection.close();
            System.out.println("\nThread closed.");
        } catch (IOException ex) {
            Logger.getLogger(MainServer.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                bufferedInputStream.close();
            } catch (IOException ex) {
                Logger.getLogger(MainServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

}
    
    public static void main(String[] args){
        int mainServerPort = 20000;
        int counter = 0;
        fileList = new ArrayList();
        try {
            ServerSocket mainServerSocket = new ServerSocket(mainServerPort);
            System.out.println("MainServer Initialized");
            while (true){
                System.out.println("\nLoop:");
                Socket mainServerConnection = mainServerSocket.accept();
                Thread thread = new Thread(new MainServer(mainServerConnection, ++counter));
                thread.start();
            }
        } 
        catch (IOException ex) {
            Logger.getLogger(MainServer.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }
    
    public class File {
        private String fileName;
        private List<String> whoHasMe;
        private boolean beingWriten;
        
        public File(String fileName, String iHaveYou){
            this.fileName = fileName;
            this.whoHasMe = new ArrayList();
            this.whoHasMe.add(iHaveYou);
            this.beingWriten = false;
        }
        
        public String getFileName(){
            return this.fileName;
        }
        
        public List<String> getWhoHasMe(){
            return this.whoHasMe;
        }
    }
}
    
